package index

import (
	"bytes"
	"gitee.com/Cauchy_AQ/gokv/data"
	"github.com/Workiva/go-datastructures/common"

	"github.com/google/btree"
)

// Indexer 抽象索引接口，后续接入其他数据结构，需要实现该接口
type Indexer interface {
	// Put 向索引中存储 key 对应的数据位置信息
	Put(key []byte, pos *data.LogRecordPos) *data.LogRecordPos

	// Get 根据 key 取出对于索引位置信息
	Get(key []byte) *data.LogRecordPos

	// Delete 根据 key 删除对于索引位置信息
	Delete(key []byte) (*data.LogRecordPos, bool)

	// Iterator 索引迭代器
	Iterator(reverse bool) Iterator

	// Size 获取数据数量大小
	Size() int

	// Close 关闭索引
	Close() error
}

type IndexType = int8

const (
	// BTree B树索引
	Btree IndexType = iota + 1

	// ART 自适应基数树索引
	ART

	// B+ 树索引
	BPTree // TODO: BUG 待完成

	// SkipList 跳表索引
	SKIP
)

func NewIndexer(idx IndexType, dirPath string, sync bool) Indexer {
	switch idx {
	case Btree:
		return NewBTree()
	case ART:
		return NewART()
	case BPTree:
		return NewBPlusTree(dirPath, sync)
	case SKIP:
		return NewSkipList()
	default:
		panic("unsupported index type")
	}
}

// Item 实现 btree.Item 接口方法 Less
type Item struct {
	key []byte
	pos *data.LogRecordPos
}

func (i *Item) Less(bi btree.Item) bool {
	return bytes.Compare(i.key, bi.(*Item).key) == -1
}

func (i *Item) Compare(comparator common.Comparator) int {
	other := comparator.(*Item)
	return bytes.Compare(i.key, other.key)
}

// Iterator 通用索引迭代器
// 为了适配不同的索引类型，也能服务上层调用
type Iterator interface {
	// Rewind 重新返回迭代起点
	Rewind()

	// Seek 根据传入 key 找到第一个大于（或小于）等于的目标 key，根据这个 key 开始遍历
	Seek(key []byte)

	// Next 跳转到下一个 key
	Next()

	// Valid 是否有效，判断是否遍历完了 key
	Valid() bool

	// Key 获取迭代器当前位置的 key
	Key() []byte

	// Value 获取当前迭代位置的索引位置信息
	Value() *data.LogRecordPos

	// Close 关闭迭代器
	Close()
}
